# -*- coding: utf-8 -*-

import paho.mqtt.client as mqtt
import os
import  time
import  hashlib
import  re
import sys
import subprocess
import  threading
import signal
import logging
from multiprocessing import Process
import  json
import asyncio
import shutil
from paho.mqtt.properties import readInt16
import requests
from publishVer  import pubVer
from queue import Queue,LifoQueue,PriorityQueue

def sigint_handler(signum, frame):
  global is_sigint_up
  is_sigint_up = True


signal.signal(signal.SIGINT, sigint_handler)

is_sigint_up = False

class  mqttRun():
    def __init__(self):
        self.RUN    = False
        self.logger = logging.getLogger('mainServer')
        self.logger.setLevel(level=logging.INFO)
        LOG_FORMAT = '%(asctime)s.%(msecs)03d line:%(lineno)d %(levelname)s %(message)s'
        DATE_FORMAT = '%Y-%m-%d %X'
        console = logging.StreamHandler()
        formatter = logging.Formatter(fmt=LOG_FORMAT, datefmt=DATE_FORMAT)
        console.setFormatter(formatter)
        logging.basicConfig(level=logging.DEBUG,#控制台打印的日志级别
                    filename='new.log',
                    filemode='a',##模式，有w和a，w就是写模式，每次都会重新写日志，覆盖之前的日志
                    #a是追加模式，默认如果不写的话，就是追加模式
                    format=LOG_FORMAT
                    #日志格式
                    )
        console.setLevel(logging.INFO)
        self.slefTest = False
        self.logger.addHandler(console)
        self.AIRSOURCE = "D:\\wsyw"
        self.FormalVerList = {}
        self.RefreshFormalVerList()
        self.BUILD_FAIL = 1
        self.mqttClient = False
        self.BUILD_SUCCESS = 0
        self.mesQueue = Queue(maxsize=0)
        self.funcs = {
        'BL': 'BLE',
        'TS': 'TTS',
        'CM': 'CAMERA',
        'LL': 'LVGL',
        'SD': 'SD',
        'FT': 'FLOAT',
        'VT': 'VOLTE',
        'RT': 'RTMP',
        'NO': 'NONE',
        'MP1': 'MIPI',
        'MP2': 'MIPI',
        'MS': 'MSC',
        'QX':'QXRTK',
        'XY':'XYRTK',
        'PB':'PB',
        'ZZ':'ZZIP',
        }  
        

    def on_connect(self,client, userdata, flags, rc):
        self.logger.info("on_connect return code:%s"%rc)
        self.logger.info("session present:%s"%(flags['session present']))

    def on_disconnect(self,client, userdata, flags):
        self.logger.info("on_disconnect return code:%s"%flags)


    def startMqtt(self):
        while(True):
         
            MQTTHOST = "120.55.137.106"
            MQTTPORT = 1883
            client_id = "airm2m_hefei1"
            if self.mqttClient :
                self.logger.info("disconnect and reopen")
                raise Exception("connect err")
            self.mqttClient = mqtt.Client(client_id)
            self.mqttClient.on_connect  = self.on_connect
            self.mqttClient.on_disconnect  = self.on_disconnect
            self.mqttClient.username_pw_set("custom_fw_gen_client","b4G4KTGO")
            connect = self.mqttClient.connect(MQTTHOST, MQTTPORT, 10)
            loop_start = self.mqttClient.loop_start()
            break
    
                
            


        pass 

    def RefreshFormalVerList(self):
        lists = os.listdir(self.AIRSOURCE+"\\VERSION")
        for i in lists:
            if i not in self.FormalVerList:
                self.FormalVerList[i]  =False
                
                
    def execute_command(self, cmd):
        self.logger.info('start executing cmd... %s'%cmd)
    
        executecommand = subprocess.Popen(str(cmd), shell=True, stdin=subprocess.PIPE, stderr=subprocess.STDOUT,
                                            stdout=subprocess.PIPE)
        line = executecommand.stdout.readline()

        while line:
            line = executecommand.stdout.readline()
            if line :
                try:
                    line =  str(line, encoding = "gbk")
                except Exception as e:
                    line = str(line)

                MMM = re.match("\[(\d+)/(\d+)\]",line)
                if MMM :
                    self.logger.info("%s %s"%(MMM.group(1),MMM.group(2)))
                    if MMM.group(1) == MMM.group(2):
                        executecommand.kill()
                        return True
            else:
                break
        executecommand.kill()
        return False

 
            
    def  splite_mes(self,mes):
        dictS = json.loads(mes)
        function =  dictS["function"]
        version = dictS["version"]
        token_id = dictS["token_id"]
        
        return function,version,token_id
    
    def  publish(self,path,token_id,res):
        pubHandle = pubVer()
        pubHandle.publish(path,token_id,res)
        pass
    

    
    def complatThread(self,version,function,token_id):
        try:
            baseCmd = "build_lua_va.bat build --functions "
            if os.path.exists(self.AIRSOURCE+"\\VERSION\\"+version+"\\hex") :
                shutil.rmtree(self.AIRSOURCE+"\\VERSION\\"+version+"\\hex")   
            os.chdir(self.AIRSOURCE+"\\VERSION\\"+version)
            for i in function:
                if i in self.funcs :
                    baseCmd =  baseCmd  + self.funcs[i] + " "
                else:
                    return False

            baseCmd = baseCmd + " --release"
            self.logger.info("complatThread %s"%baseCmd)
            for i in range(0,5):
                if self.execute_command(baseCmd):
                    self.logger.info("build sucess")
                    self.publish(self.AIRSOURCE+"\\VERSION\\"+version+"\\hex",token_id,self.BUILD_SUCCESS)
                    return True
                else:
                    if i > 3:
                        if os.path.exists(self.AIRSOURCE+"\\VERSION\\"+version+"\\out") :
                            shutil.rmtree(self.AIRSOURCE+"\\VERSION\\"+version+"\\out")   
                    self.logger.info("build fail %d"%i)
                    
            os.chdir(self.AIRSOURCE)
            return False
            
        except Exception as  e:
            self.logger.info("build fail")
            self.publish(False,token_id,self.BUILD_FAIL)
        
        
        pass
    

    
 

    def on_message_come(self,lient, userdata, msg):
        self.logger.info("topic:%s len:%d %s"%(msg.topic , len(msg.payload),msg.payload))
        try:
            payload =  str(msg.payload, encoding = 'gbk')
            if msg.topic == "/erp/custom_firmware/gen":                                     #测试请求
                if str(msg.payload,encoding="gbk").find("test") != -1:
                    self.slefTest = True
                elif str(msg.payload,encoding="gbk").find("vvv") == -1:
                    self.mesQueue.put(str(msg.payload,encoding="gbk"))
                
                    print("now request is %d"%self.mesQueue.qsize())

                pass
            
        except Exception as  e:
            self.logger.warning("on_message_come err %s"%e)
            payload = str(msg.payload)
        


            
    def buildVersionThread(self):
        while(True):
            if self.mesQueue.qsize() > 0:
                payload = self.mesQueue.get()
                self.mesQueue.task_done()
                function,version,token_id  =  self.splite_mes(payload)
                print("buildVersionThread  function:%s version:%s token_id:%s"%(function,version,token_id))
                self.RefreshFormalVerList()
                if self.RUN == False:
                    self.RUN = True
                    self.complatThread(version,function,token_id)
                    self.RUN = False
            time.sleep(1)

    def buildCriThread(self):
        while(True):
            self.slefTest = False
            self.on_publish("/erp/custom_firmware/gen","test",0)
            time.sleep(1)
            self.on_publish("/erp/custom_firmware/gen","test",0)
            time.sleep(1)
            self.on_publish("/erp/custom_firmware/gen","test",0)
            time.sleep(6)
            if not self.slefTest :
                self.startMqtt()
            time.sleep(60)


        pass


    def on_publish(self,topic,mes,qos):
        self.mqttClient.publish(topic, mes, qos)

        pass

    def on_subscribe(self):
        self.mqttClient.subscribe("/erp/custom_firmware/gen", 1)
        self.mqttClient.on_message = self.on_message_come  
    

    def run(self):
        self.startMqtt()
        self.on_subscribe()
        threading.Thread(target=self.buildVersionThread).start()
        threading.Thread(target=self.buildCriThread).start()
        while(True):
            global is_sigint_up
            if is_sigint_up:
                is_sigint_up = False
                sys.exit()
            time.sleep(2)



if __name__ == '__main__':
    while True:
        try:
            handle = mqttRun()
            # handle.buildVersion('V3027',['BT','CM','LL'],33)
            handle.run()
        except Exception as e:
            continue



